﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using EmitMapper;
using EmitMapper.MappingConfiguration;

namespace AF_Tools
{
    public static class Mapper
    {
        /// <summary>
        /// 将TForm类型的对象映射为TTo类型
        /// </summary>
        /// <typeparam name="TFrom"></typeparam>
        /// <typeparam name="TTo"></typeparam>
        /// <param name="from"></param>
        /// <returns></returns>
        public static TTo Map<TFrom, TTo>(TFrom from)
        {
            ObjectsMapper<TFrom, TTo> Mapper = new ObjectMapperManager().GetMapper<TFrom, TTo>();
            return Mapper.Map(from);
        }

        /// <summary>
        /// 将From合并到To
        /// </summary>
        /// <typeparam name="TFrom"></typeparam>
        /// <typeparam name="TTo"></typeparam>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public static TTo Map<TFrom, TTo>(TFrom from, TTo to)
        {
            ObjectsMapper<TFrom, TTo> Mapper = new ObjectMapperManager().GetMapper<TFrom, TTo>();
            return Mapper.Map(from, to);
        }

        /// <summary>
        /// 将TForm类型的对象映射为TTo类型，忽略指定的成员
        /// </summary>
        /// <typeparam name="TFrom"></typeparam>
        /// <typeparam name="TTo"></typeparam>
        /// <param name="from"></param>
        /// <param name="ignoreMembers"></param>
        /// <returns></returns>
        public static TTo Map<TFrom, TTo>(TFrom from, params Expression<Func<TFrom, dynamic>>[] ignoreMembers)
        {
            List<string> ignoreMemberList = new List<string>();
            foreach (var item in ignoreMembers)
            {
                var ignoreExp = GetMemberInfo(item);
                ignoreMemberList.Add(ignoreExp.ToString());
            }

            var Mapper = ObjectMapperManager.DefaultInstance.GetMapper<TFrom, TTo>(
                    new DefaultMapConfig().IgnoreMembers<TFrom, TTo>(ignoreMemberList.ToArray()));
            return Mapper.Map(from);
        }

        public static TTo Map<TFrom, TTo>(TFrom from, DefaultMapConfig mapConfig)
        {
            var Mapper = ObjectMapperManager.DefaultInstance.GetMapper<TFrom, TTo>(mapConfig);
            return Mapper.Map(from);
        }

        private static MemberExpression GetMemberInfo(LambdaExpression lambda)
        {
            if (lambda == null)
                throw new ArgumentNullException("method");

            MemberExpression memberExpr = null;

            if (lambda.Body.NodeType == ExpressionType.Convert)
            {
                memberExpr =
                    ((UnaryExpression)lambda.Body).Operand as MemberExpression;
            }
            else if (lambda.Body.NodeType == ExpressionType.MemberAccess)
            {
                memberExpr = lambda.Body as MemberExpression;
            }

            if (memberExpr == null)
                throw new ArgumentException("method");

            return memberExpr;
        }
    }
}
